package com.afdor.rws.event.config;

import org.apache.commons.lang3.StringUtils;

import java.util.Map;
import java.util.Properties;

/**
 * 获取配置信息
 *
 * @author 悭梵
 * @date Created in 2018-08-09 9:40
 */
public final class EventConfigUtils {

    /**
     * 事件ID 生成策略，扩展点名称。默认uuid，由IdGeneratorStrategy.SPI("uuid")负责激活默认值
     */
    public static final String EVENT_STRATEGY_NAME_ID = "rws.event.id";
    /**
     * 事件时间获取策略，扩展点名称。默认local_timestamp，由TimestampStrategy.SPI("local_timestamp")负责激活默认值
     */
    public static final String EVENT_STRATEGY_NAME_TIMESTAMP = "rws.event.timestamp";
    /**
     * 事件源，扩展点名称。默认default，由EventSource.SPI("default")负责激活默认值
     */
    public static final String EVENT_SOURCE_NAME = "rws.event.source.name";
    /**
     * 事件源管理器，扩展点名称。默认default，由EventSourceManager.SPI("default")负责激活默认值
     */
    public static final String EVENT_SOURCE_MANAGER_NAME = "rws.event.source.manager.name";
    /**
     * 事件持久化管理器，扩展点名称。默认default，由EventPersistenceManager.SPI("default")负责激活默认值
     */
    public static final String EVENT_PERSISTENCE_MANAGER_NAME = "rws.event.persistence.manager.name";
    /**
     * 事件持久化处理间隔事件，单位毫秒，默认1000
     */
    public static final String EVENT_PERSISTENCE_PERIOD = "rws.event.persistence.manager.period";
    /**
     * 事件持久化一次处理的事件量，默认50
     */
    public static final String EVENT_PERSISTENCE_BATCH_SIZE = "rws.event.persistence.manager.batch_size";
    /**
     * 自定义事件总线扩展点名称。默认default，有EventBus.SPI("default")负责激活默认值
     */
    public static final String EVENT_EVENT_BUS_NAME = "rws.event.eventbus.name";
    /**
     * 聚合根事件是否发送，默认不发送
     */
    public static final String EVENT_EVENT_BUS_IS_SEND_AGGREGATION_ROOT_EVENT = "rws.event.eventbus.aggregation.send";
    /**
     * 事件总线中事物ID 生成策略，扩展点名称。默认uuid，由IdGeneratorStrategy.SPI("uuid")负责激活默认值
     */
    public static final String EVENT_EVENT_BUS_TRANSACTION_ID = "rws.event.eventbus.transaction.id";
    /**
     * 事件传递通道扩展点名称，必填。各种实现方式，默认值不一样
     */
    public static final String EVENT_CHANNEL_NAME = "rws.event.channel.name";
    /**
     * 消费者扩展点名称，必填。各种实现方式，存在默认值不一样情况
     */
    public static final String EVENT_CONSUMER_NAME = "rws.event.channel.consumer.name";
    /**
     * 消费者事件重试策略扩展点名称。默认default，由EventRetryStrategy.SPI("default")负责激活默认值。该默认值只做持久化，未做重试，谨慎使用
     */
    public static final String EVENT_CONSUMER_RETRY_NAME = "rws.event.channel.consumer.retry.name";
    /**
     * 最大重试次数。默认3,但各种实现方式，存在默认值不一样情况
     */
    public static final String EVENT_CONSUMER_MAX_RETRY_NUM = "rws.event.channel.consumer.retry.num";
    /**
     * 生产者扩展点名称，必填。各种实现方式，存在默认值不一样情况
     */
    public static final String EVENT_PRODUCER_NAME = "rws.event.channel.producer.name";
    /**
     * 事件序列化扩展点名称，必填。各种实现方式，存在默认值不一样情况
     */
    public static final String EVENT_CHANNEL_SERIALIZATION_NAME = "rws.event.channel.serialization.name";
    /**
     * 默认广播事件处理器名称，允许为空。
     */
    public static final String EVENT_CONSUMER_HANDLER_DEFAULT_BROADCAST_NAME = "rws.event.channel.consumer.broadcast.name";
    /**
     * 默认骨架事件处理器名称，允许为空。
     */
    public static final String EVENT_CONSUMER_HANDLER_DEFAULT_AGGREGATION_ROOT_NAME = "rws.event.channel.consumer.aggregationRoot.name";
    /**
     * 消费者监听事件处理间隔事件，单位毫秒，默认1000
     */
    public static final String EVENT_CONSUMER_HANDLER_PERIOD = "rws.event.channel.consumer.handler.period";
    /**
     * 采用副本事件拦截链进行拦截，默认：false。在拦截链比较固定的情况下，推荐false，若拦截链经常动态变化，推荐true。
     */
    public static final String EVENT_INTERCEPT_CHAIN_CLONE = "rws.event.intercept.chain.clone";
    /**
     * 生产者事件拦截链的扩展点名称，允许为空。
     */
    public static final String EVENT_PRODUCER_INTERCEPT_CHAIN_NAME = "rws.event.channel.producer.intercept.chain.name";
    /**
     * 消费者事件拦截链的扩展点名称，允许为空。
     */
    public static final String EVENT_CONSUMER_INTERCEPT_CHAIN_NAME = "rws.event.channel.consumer.intercept.chain.name";
    /**
     * 获取消息阻塞时间。默认-1，小于等于0时，不调用阻塞获取方法。不推荐阻塞获取。
     */
    public static final String EVENT_CONSUMER_GET_MESSAGE_TIMEOUT = "rws.event.channel.consumer.get_message.timeout";
    /**
     * 一次获取消息的数量，默认：8，各种实现方式，存在默认值不一样情况
     */
    public static final String EVENT_CONSUMER_GET_MESSAGE_BATCH_SIZE = "rws.event.channel.consumer.get_message.batch_size";

    private static EventConfig globalConfig;

    static {
        Properties properties = new Properties();
        try {
            properties.load(EventConfigUtils.class.getResourceAsStream("/META-INF/rws/internal/core.properties"));
        } catch (Exception e) {
        }
        if (!properties.isEmpty()) {
            globalConfig = new EventConfig((Map) properties);
        }
    }

    /**
     * 全局配置
     *
     * @return
     */
    public static EventConfig getGlobalConfig() {
        return globalConfig;
    }

    /**
     * 请在主线程中设置
     *
     * @param globalConfig
     */
    public static void setGlobalConfig(EventConfig globalConfig) {
        if (globalConfig == null) {
            throw new NullPointerException("配置信息为空");
        }
        if (EventConfigUtils.globalConfig == null) {
            synchronized (EventConfigUtils.class) {
                if (EventConfigUtils.globalConfig == null) {
                    EventConfigUtils.globalConfig = globalConfig;
                } else {
                    EventConfigUtils.globalConfig.addAll(globalConfig);
                }
            }
        } else {
            EventConfigUtils.globalConfig.addAll(globalConfig);
        }
    }

    /**
     * 按优先级获取配置信息<br/>
     * 取值顺序：全局配置 -> 应用启动参数 -> 环境变量
     *
     * @param key
     * @return
     */
    public static String getProperty(String key) {
        return getProperty(key, null);
    }

    /**
     * 按优先级获取配置信息<br/>
     * 取值顺序：全局配置 -> 应用启动参数 -> 环境变量 -> 默认值
     *
     * @param key
     * @param defaultValue 默认值
     * @return
     */
    public static String getProperty(String key, String defaultValue) {
        return getProperty(globalConfig, key, defaultValue);
    }

    /**
     * 按优先级获取配置信息并指定配置信息<br/>
     * 取值顺序：入参配置 -> 全局配置 -> 应用启动参数 -> 环境变量
     *
     * @param properties
     * @param key
     * @return
     */
    public static String getProperty(Map<String, String> properties, String key) {
        return getProperty(properties, key, null);
    }

    /**
     * 按优先级获取配置信息并指定配置信息<br/>
     * 取值顺序：入参配置 -> 全局配置 -> 应用启动参数 -> 环境变量 -> 默认值
     *
     * @param properties
     * @param key
     * @param defaultValue
     * @return
     */
    public static String getProperty(Map<String, String> properties, String key, String defaultValue) {
        // 从指定配置中获取配置信息
        String value = properties == null ? null : properties.get(key);

        if (StringUtils.isBlank(value)) {
            value = getProperty(globalConfig, key, defaultValue);
        }

        return StringUtils.isBlank(value) ? defaultValue : value;
    }

    /**
     * 按优先级获取配置信息并指定配置信息<br/>
     * 取值顺序：入参配置 -> 全局配置 -> 应用启动参数 -> 环境变量
     *
     * @param properties
     * @param key
     * @return
     */
    public static String getProperty(Properties properties, String key) {
        return getProperty(properties, key, null);
    }

    /**
     * 按优先级获取配置信息并指定配置信息<br/>
     * 取值顺序：入参配置 -> 全局配置 -> 应用启动参数 -> 环境变量 -> 默认值
     *
     * @param properties
     * @param key
     * @param defaultValue
     * @return
     */
    public static String getProperty(Properties properties, String key, String defaultValue) {
        // 从指定配置中获取配置信息
        String value = properties == null ? null : properties.getProperty(key);

        if (StringUtils.isBlank(value)) {
            value = getProperty(globalConfig, key, defaultValue);
        }

        return StringUtils.isBlank(value) ? defaultValue : value;
    }


    /**
     * 按优先级获取配置信息并指定配置信息<br/>
     * 取值顺序：入参配置 -> 全局配置 -> 应用启动参数 -> 环境变量
     *
     * @param config
     * @param key
     * @return
     */
    public static String getProperty(EventConfig config, String key) {
        return getProperty(config, key, null);
    }

    /**
     * 按优先级获取配置信息并指定配置信息<br/>
     * 取值顺序：入参配置 -> 全局配置 -> 应用启动参数 -> 环境变量 -> 默认值
     *
     * @param config
     * @param key
     * @param defaultValue
     * @return
     */
    public static String getProperty(EventConfig config, String key, String defaultValue) {
        // 从指定配置中获取配置信息
        String value = config == null ? null : config.getProperty(key);

        if (StringUtils.isBlank(value) && config != globalConfig) {
            value = getProperty(globalConfig, key, defaultValue);
        }

        if (StringUtils.isBlank(value)) {
            value = getEnvironmentProperty(key, defaultValue);
        }

        return StringUtils.isBlank(value) ? defaultValue : value;
    }

    /**
     * 按优先级获取配置信息<br/>
     * 取值顺序：应用启动参数 -> 环境变量
     *
     * @param key
     * @return
     */
    public static String getEnvironmentProperty(String key) {
        return getEnvironmentProperty(key, null);
    }

    /**
     * 按优先级获取配置信息<br/>
     * 取值顺序： 应用启动参数 -> 环境变量 -> 默认值
     *
     * @param key
     * @param defaultValue 默认值
     * @return
     */
    public static String getEnvironmentProperty(String key, String defaultValue) {
        // 优先从程序启动信息中获取配置
        String value = System.getProperty(key);
        // 最后从环境变量获取配置
        if (StringUtils.isBlank(value)) {
            value = System.getenv(key);
        }

        return StringUtils.isBlank(value) ? defaultValue : value;
    }
}
